#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#include <functional>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <cstdlib>
#include <cstring>
#include <strings.h>
#include <cstdio>
#include "protocol.hpp"
#define NUM 1024
enum
{
    USAGE_ERR = 1,
    SOCKET_ERR,
    BIND_ERR,
    LISTEN_ERR,
    FORK_ERR,
    WAIT_ERR
};
namespace Server
{
    using func_t = std::function<bool(const Request &, Response &)>;

    class HttpServer
    {
        static const int gbacklog = 5;

    public:
        HttpServer(func_t func, const uint16_t port)
            : _func(func), _port(port), _listensock(-1)
        {
        }
        void initServer()
        {
            // 1.创建socket套接字对象
            _listensock = socket(AF_INET, SOCK_STREAM, 0);
            if (_listensock == -1)
            {

                exit(SOCKET_ERR);
            }

            // 2.绑定ip和端口
            struct sockaddr_in local;
            bzero(&local, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;
            if (bind(_listensock, (struct sockaddr *)&local, sizeof(local)) != 0)
            {
                exit(BIND_ERR);
            }

            // 3.设置socket为监听状态
            if (listen(_listensock, gbacklog) < 0)
            {
                exit(LISTEN_ERR);
            }
        }
        void start()
        {

            while (1)
            {
                // 接受远端连接
                struct sockaddr_in client;
                socklen_t len = sizeof(client);
                int sockfd = accept(_listensock, (struct sockaddr *)&client, &len);
                if (sockfd == -1)
                {
                    continue;
                }
                // 多进程 孙子进程处理
                pid_t id = fork();
                if (id == 0) // 子进程
                {
                    close(_listensock);
                    if (fork() > 0)
                        exit(0); // 创造孙子进程，子进程先退出，孙子进程变成孤儿进程，由os领养，优雅但不高效
                    handlerHttp(sockfd);
                    close(sockfd);
                    exit(0);
                }
                else if (id == -1)
                {
                    exit(FORK_ERR);
                }
                close(sockfd);
                waitpid(id, nullptr, 0);
            }
        }

        void handlerHttp(int sockfd)
        {
            char buffer[4096];
            //while (true)
            {
                // 1.读取一个完整的请求报文
                // 2.去掉请求报文的报头，得到请求正文
                // 3.将请求正文反序列化
                // 4.业务逻辑，得到响应结构体
                // 5.将响应结构体序列化
                // 6.将响应添加报头
                // 7.发送响应

                ssize_t n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
                Request req;
                Response resp;
                if (n > 0)
                {
                    buffer[n] = 0;
                    req.inbuffer = buffer;
                    req.parse();
                     _func(req, resp);
                    // _funcs[req.path](req, resp);
                    send(sockfd, resp.outbuffer.c_str(), resp.outbuffer.size(), 0);
                }
            }

            close(sockfd);
        }

        void registerCb(const std::string &name, func_t func)
        {
            // _funcs.insert(std::make_pair(name, func));
            _funcs[name] = func;
        }

        ~HttpServer()
        {
        }

    private:
        int _listensock; // 不是用来通信的，是用来监听连接到来，获取新连接的
        uint16_t _port;
        func_t _func;
        std::unordered_map<std::string, func_t> _funcs;
    };
}
